/*************************************************************************
	> File Name: thread.h
	> Author: luqingliang
	> Mail: 13420685558@163.com
	> Created Time: 2024年02月13日 星期二 19时34分45秒
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
#include <time.h>

#define THREAD_WORK_MAX 5

// 线程工作状态
enum
{
	T_FREE = 0, // init
	T_LIVE,		// work
	T_FINISH,	// work end
	T_DIE,		// join
};

typedef struct thread_work_st
{
	int id;		// work id
	int status; // work status
	pthread_t tid;
	void *(*work_func)(void *); // be called function
	void *arg;					// args
	void *ret;					// be called function
} thread_work_t;

// 简易线程池
thread_work_t pool[THREAD_WORK_MAX];
// 最后线程池地址
thread_work_t *pptr = pool;

// 方法声明
void *manager_impl(void *arg);

pthread_once_t manager_once = PTHREAD_ONCE_INIT;
// 管理者结构体
thread_work_t manager = {
	.id = 0xFFF,
	.status = T_LIVE,
	.work_func = manager_impl,
	.arg = NULL,
};

// 外层包装 WARN 会清空栈帧 导致void *类型数据 直接跑飞
void *work_impl(void *worker)
{
	thread_work_t *tmp = (thread_work_t *)worker;
	tmp->ret = tmp->work_func(tmp->arg);
	tmp->status = T_FINISH;
	// printf("thread(%ld) finish ret:%p(data:%d)\n", tmp->tid, tmp->ret, *(int *)tmp->ret);
	pthread_exit(tmp);
	// return NULL;
}

// 管理者函数
void *manager_impl(void *arg)
{
	// 休眠时间
	struct timespec sleep_time, remaining_time;
	// 1秒（1000000000纳秒）
	sleep_time.tv_sec = 1;
	sleep_time.tv_nsec = 0;

	thread_work_t *mptr = pool;
	while (1)
	{
		for (int i = 0; i < THREAD_WORK_MAX; i++)
		{
			mptr = &pool[i];
			if (mptr->status == T_FINISH)
			{
				void *ret = NULL;
				pthread_join(mptr->tid, &ret);
				thread_work_t *tmp = (thread_work_t *)ret;
				// printf("manager(%ld) =>thread(%ld) finish ret:%p(data:%d)\n", manager.tid, tmp->tid, tmp->ret, *(int *)tmp->ret);
				mptr->status = T_DIE;
			}
		}

		// 使用nanosleep进行休眠
		nanosleep(&sleep_time, &remaining_time);
		// 如果nanosleep提前返回（因为被信号中断），remaining_time将包含未休眠的时间
		if (remaining_time.tv_sec > 0 || remaining_time.tv_nsec > 0)
			sleep_time = remaining_time;
	}
}

void _create_manager(void)
{
	int ret = pthread_create(&(manager.tid), NULL, manager.work_func, NULL);
	if (ret != 0)
		printf("manager thread init fail\n");
	manager.ret = &ret;
}

// 创建任务函数
int _create(void *func, void *arg)
{
	if (pptr - pool == (THREAD_WORK_MAX - 1)) // ptr到下标为63了 重置
		pptr = pool;
	while (pptr - pool < THREAD_WORK_MAX) // 遍历后面的线程池对象
	{
		if (pptr->status == T_DIE || pptr->status == T_FREE) // 线程结束 或 初始化完毕
		{
			*pptr = (thread_work_t){
				.id = pptr - pool,
				.status = T_LIVE,
				.work_func = func,
				.arg = arg,
				.ret = NULL,
			};
			if (pthread_create(&(pptr->tid), NULL, work_impl, pptr) == 0)
			{
				int id = pptr->id;
				++pptr;
				return id;
			}
			else
				return -100; // 存在资源但启动线程失败
		}
		++pptr;
	}
	return -1; // 暂无资源可用
}

// 用户调用的创建任务的函数
int create(void *func, void *arg)
{
	pthread_once(&manager_once, _create_manager);
	return _create(func, arg);
}

// 打印线程池状态
void print_pool_status()
{
	char buf[6 * 3 + (THREAD_WORK_MAX * 12 + 3) * 2] = {0};

	strcat(buf, "(id,status) : [");
	for (int i = 0; i < THREAD_WORK_MAX; i++)
	{
		thread_work_t *t = &pool[i];
		char status_str[10];
		sprintf(status_str, "(%d,%d)", t->id, t->status);
		strcat(buf, status_str);
		if (i != (THREAD_WORK_MAX - 1))
			strcat(buf, " , ");
	}
	strcat(buf, "]\n");

	printf("%s\n", buf);
}

void join()
{
	pthread_join(manager.tid, NULL);
}

// man 3 atexit
__attribute__((destructor)) void cleanup()
{
	join();
}
